package com.arpa.oms.service.impl;

import cn.hutool.core.util.IdUtil;
import com.arpa.ntocc.common.common.exception.ServiceException;
import com.arpa.ntocc.common.common.util.CommonUtil;
import com.arpa.ntocc.common.common.util.UserUtil;
import com.arpa.oms.domain.dto.OmsPayableDetailDTO;
import com.arpa.oms.domain.entity.OmsPayableDetail;
import com.arpa.oms.domain.vo.OmsPayableDetailVO;
import com.arpa.oms.mapper.OmsPayableDetailMapper;
import com.arpa.oms.service.IOmsPayableDetailService;
import com.arpa.wms.common.util.BigDecimalUtil;
import com.arpa.wms.domain.dto.ExpenseDetailSettlementDTO;
import com.arpa.wms.domain.enums.ExpenseDetailStatusEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.Future;

/**
 * <p>
 * OMS应付明细 服务实现类
 * </p>
 *
 * @author LEO
 * @since 2020-12-04
 */
@Service
@Log4j2(topic = "business")
public class OmsPayableDetailServiceImpl extends ServiceImpl<OmsPayableDetailMapper, OmsPayableDetail> implements IOmsPayableDetailService {

    /**
     * 保存
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public boolean save(OmsPayableDetail entity) {
        if(StringUtils.isBlank(entity.getCode())){
            entity.setCode(IdUtil.simpleUUID());
        }
        if(StringUtils.isBlank(entity.getCreatedBy())){
            entity.setCreatedBy(UserUtil.getCode());
        }
        //设置金额类 保留两位小数四舍五入
        entity.setAmountMoney(BigDecimalUtil.getNumber(entity.getAmountMoney()));
        entity.setSettledMoney(BigDecimalUtil.getNumber(entity.getSettledMoney()));
        entity.setUnsettledMoney(BigDecimalUtil.getNumber(entity.getUnsettledMoney()));
        entity.setWaitingSettledMoney(BigDecimalUtil.getNumber(entity.getWaitingSettledMoney()));
        entity.setAmountReduce(BigDecimalUtil.getNumber(entity.getAmountReduce()));
        return super.save(entity);
    }

    /**
     * 根据code更新实体
     * @param entity
     * @return
     */
    @Override
    @Transactional(rollbackFor={Exception.class})
    public int updateByCode(OmsPayableDetail entity) {
        if(StringUtils.isBlank(entity.getModifiedBy())){
            entity.setModifiedBy(UserUtil.getCode());
        }
        //设置金额类 保留两位小数四舍五入
        entity.setAmountMoney(BigDecimalUtil.getNumber(entity.getAmountMoney()));
        entity.setSettledMoney(BigDecimalUtil.getNumber(entity.getSettledMoney()));
        entity.setUnsettledMoney(BigDecimalUtil.getNumber(entity.getUnsettledMoney()));
        entity.setWaitingSettledMoney(BigDecimalUtil.getNumber(entity.getWaitingSettledMoney()));
        entity.setAmountReduce(BigDecimalUtil.getNumber(entity.getAmountReduce()));
        return baseMapper.update(entity,new QueryWrapper<OmsPayableDetail>().lambda().eq(OmsPayableDetail::getCode,entity.getCode()));
    }

    /**
     * 查询列表
     * @param omsPayableDetailDTO
     * @return
     */
    @Override
    public List<OmsPayableDetailVO> queryList(OmsPayableDetailDTO omsPayableDetailDTO){
        //排序字段名需要驼峰转数据库下划线类型字段名
        if(StringUtils.isNotEmpty(omsPayableDetailDTO.getSortField())){
            omsPayableDetailDTO.setSortField(CommonUtil.camel2Underline(omsPayableDetailDTO.getSortField()));
        }
        List<OmsPayableDetailVO> omsPayableDetailVOList = baseMapper.queryList(omsPayableDetailDTO);
        return omsPayableDetailVOList;
    }

    /**
     * 查询合计,包含总数
     * @param omsPayableDetailDTO
     * @return
     */
    @Override
    public OmsPayableDetailVO queryListSum(OmsPayableDetailDTO omsPayableDetailDTO){
        OmsPayableDetailVO omsPayableDetailVO = baseMapper.queryListSum(omsPayableDetailDTO);
        return omsPayableDetailVO;
    }


    @Override
    public Future check(ExpenseDetailSettlementDTO.SettlementItem settlementItem) {
        OmsPayableDetail one = super.getOne(new QueryWrapper<OmsPayableDetail>().lambda()
                .eq(OmsPayableDetail::getCode, settlementItem.getCode())
        );
        if (null == one) {
            log.error("找不到费用明细。CODE【{}】", settlementItem.getCode());
            throw new ServiceException("找不到费用明细");
        }
        if (one.getStatus().equals(ExpenseDetailStatusEnum.SETTLED)) {
            log.error("已进行结算，不能重复结算。CODE【{}】", settlementItem.getCode());
            throw new ServiceException("已进行结算，不能重复结算");
        }
        if (settlementItem.getThisSettledMoney().compareTo(BigDecimal.ZERO) == 0) {
            log.error("结算金额【{}】不能等为0", settlementItem.getThisSettledMoney());
            throw new ServiceException("结算金额【{}】不能等为0");
        }
        //TODO 负数情况下是否判断不能超过0
        BigDecimal temp = one.getAmountMoney().subtract(one.getSettledMoney()).subtract(one.getWaitingSettledMoney());
        if (settlementItem.getThisSettledMoney().abs().compareTo(temp.abs()) > 0) {
            log.error("本次结算金额【{}】不能超过未结算金额【{}】", settlementItem.getThisSettledMoney(), temp);
            throw new ServiceException("本次结算金额【" + settlementItem.getThisSettledMoney() + "】不能超过未结算金额【" + temp + "】");
        }
        return new AsyncResult(true);
    }

    /**
     * 生成结算单时更新费用金额
     *
     * @param code             费用明细标识
     * @param thisSettledMoney 本次结算金额
     * @param byCode           操作人code
     * @param name             操作人姓名
     */
    @Override
    public void updateSettlementMoney(String code, BigDecimal thisSettledMoney, String byCode, String name) {
        baseMapper.updateSettlementMoney(code,  BigDecimalUtil.getNumber(thisSettledMoney),  byCode,  name);
    }

    /**
     * 删除、修改结算单后还原收费信息
     *
     * @param code                费用标识
     * @param restoreSettledMoney 要还原的金额
     */
    @Override
    public void restoreSettlementStatus(String code, BigDecimal restoreSettledMoney,BigDecimal reduceMoney) {
        baseMapper.restoreSettlementStatus(code, BigDecimalUtil.getNumber(restoreSettledMoney), BigDecimalUtil.getNumber(reduceMoney));
    }

    /**
     * 付款单审核通过后确认收费信息
     *
     * @param code         费用标识
     * @param confirmMoney 确认金额
     */
    @Override
    public void confirmSettlementStatus(String code, BigDecimal confirmMoney) {
        baseMapper.confirmSettlementStatus(code, BigDecimalUtil.getNumber(confirmMoney));
    }
}
